package triEngine;

import transaction.*;
import triBasic.*;
import triInstance.*;
import triIndex.*;
import triTree.*;

/**
 * the real working engine
 * Each sub-operation is considered as transaction.
 */

public class TriEngine {

	TreeManager triTree;
	IndexManager triIndex;
	TxManager txMgr;
	
	public TriEngine() {
		txMgr = new TxManager();
		triTree = new TreeManager();
		triIndex = new IndexManager();
	}
	
	public void StartUp() {
		Transaction tx = txMgr.newTransaction();
		triTree.init(tx);
		triIndex.init(tx);
		
		triTree.addCreateNodeHandler(triIndex);
		triTree.addInsertItemHandler(triIndex);
		triTree.addRemoveItemHandler(triIndex);
		
		tx.commit();
	}
	
	/*
	 * regular operation
	 */
	public boolean insert(TriItem item, TagList path) {
		Transaction tx = txMgr.newTransaction();
		try {
			return triTree.insertItem(item, path, tx);
		}
		finally {
			tx.commit();
		}
	}
	
	public boolean insert(TriItem item, NodeInfo node) {
		Transaction tx = txMgr.newTransaction();
		try {
			NodeSnapshot snapshot = triIndex.getNodeSnapshot(node, tx);
			if (snapshot == null)
				return false;
			return triTree.insertItem(item, snapshot, tx);
		}
		finally {
			tx.commit();
		}
	}

	public boolean remove(TriItem item, TagList path) {
		Transaction tx = txMgr.newTransaction();
		try {
			return triTree.removeItem(item, path, tx);
		}
		finally {
			tx.commit();
		}
	}
	
	public boolean remove(TriItem item, NodeInfo node) {
		Transaction tx = txMgr.newTransaction();
		try {
			NodeSnapshot snapshot = triIndex.getNodeSnapshot(node, tx);
			if (snapshot == null)
				return false;
			return triTree.removeItem(item, snapshot, tx);
		}
		finally {
			tx.commit();
		}
	}
	
	public ISet<String> queryItemSet(TagList path) {
		Transaction tx = txMgr.newReadTransaction();//.newTransaction();
		try {
			return triTree.queryItemSet(path, tx);
		}
		finally {
			tx.commit();
		}
	}
	
	public TriPath queryTriPath(NodeInfo node) {
		Transaction tx = txMgr.newReadTransaction();//.newTransaction();
		try {
			return triIndex.getTriPath(node, tx);
		}
		finally {
			tx.commit();
		}
	}
	
	public INode queryNode(NodeInfo node) {
		Transaction tx = txMgr.newReadTransaction();//.newTransaction();
		try {
			NodeSnapshot snapshot = triIndex.getNodeSnapshot(node, tx);
			return triTree.queryNode(snapshot, tx);
		}
		finally {
			tx.commit();
		}
	}
	
	public ISet<NodeInfo> queryItem(TriItem item) {
		Transaction tx = txMgr.newReadTransaction();//.newTransaction();
		try {
			ISet<Integer> intSet = triIndex.getItem2NodeId(item, tx);
			if (intSet == null)
				return null;
			return new NodeInfoSet(intSet, this.triIndex, tx);
		}
		finally {
			tx.commit();
		}
	}
	
	public ISet<NodeInfo> queryTag(String tagname) {
		Transaction tx = txMgr.newReadTransaction();//.newTransaction();
		try {
			ISet<Integer> intSet = triIndex.getTag2NodeId(tagname, tx);
			if (intSet == null)
				return null;
			return new NodeInfoSet(intSet, this.triIndex, tx);
		}
		finally {
			tx.commit();
		}
	}
	
	public void compactTree() {
		triTree.compact(txMgr);
	}
	
	public void compactIndex() {
		triIndex.compact(txMgr);
	}
	
	public void ShutDown() {
		Transaction tx = txMgr.newTransaction();
		this.triIndex.dispose(tx);
		this.triTree.dispose(tx);
		tx.commit();
		txMgr.dispose();
	}
	
}


